<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/dute_favicon_32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/dute_favicon_16x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">
  <link rel="manifest" href="/images/manifest.json">
  <meta name="msapplication-config" content="/images/browserconfig.xml">
  <meta http-equiv="Cache-Control" content="no-transform">
  <meta http-equiv="Cache-Control" content="no-siteapp">
  <meta name="google-site-verification" content="mpI5dkydstZXl6UcDCppqktXK0bbvqdZ6LkZ3KNk4Iw">
  <meta name="baidu-site-verification" content="code-a1LksZX2Ds">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"whitestore.top","root":"/","scheme":"Gemini","version":"7.8.0","exturl":true,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":true,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="从零开始的架构探险">
<meta property="og:type" content="article">
<meta property="og:title" content="《从零开始的架构探险》归纳总结">
<meta property="og:url" content="https://whitestore.top/2020/07/26/note4/index.html">
<meta property="og:site_name" content="爱看书的阿东">
<meta property="og:description" content="从零开始的架构探险">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://raw.githubusercontent.com/lazyTimes/imageRepository/master/img/Snipaste_2020-02-10_11-00-25.png?ynotemdtimestamp=1595748679079">
<meta property="og:image" content="http://null/">
<meta property="og:image" content="http://null/">
<meta property="og:image" content="http://null/">
<meta property="article:published_time" content="2020-07-26T09:44:54.000Z">
<meta property="article:modified_time" content="2023-07-16T06:28:09.236Z">
<meta property="article:author" content="阿东">
<meta property="article:tag" content="从零开始的架构探险">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://raw.githubusercontent.com/lazyTimes/imageRepository/master/img/Snipaste_2020-02-10_11-00-25.png?ynotemdtimestamp=1595748679079">

<link rel="canonical" href="https://whitestore.top/2020/07/26/note4/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>《从零开始的架构探险》归纳总结 | 爱看书的阿东</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="爱看书的阿东" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">爱看书的阿东</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">赐他一块白色石头，石头上写着新名</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
        <li class="menu-item menu-item-sitemap">

    <a href="/sitemap.xml" rel="section"><i class="fa fa-fw fa-sitemap"></i>站点地图</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    

  <span class="exturl github-corner" data-url="aHR0cHM6Ly9naXRodWIuY29tL2xhenlUaW1lcw==" title="Follow me on GitHub" aria-label="Follow me on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></span>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://whitestore.top/2020/07/26/note4/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="阿东">
      <meta itemprop="description" content="随遇而安">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="爱看书的阿东">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          《从零开始的架构探险》归纳总结
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-07-26 17:44:54" itemprop="dateCreated datePublished" datetime="2020-07-26T17:44:54+08:00">2020-07-26</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-07-16 14:28:09" itemprop="dateModified" datetime="2023-07-16T14:28:09+08:00">2023-07-16</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/" itemprop="url" rel="index"><span itemprop="name">读书笔记</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="fa fa-comment-o"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/2020/07/26/note4/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/2020/07/26/note4/" itemprop="commentCount"></span>
    </a>
  </span>
  
  <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>9.1k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="fa fa-clock-o"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>8 分钟</span>
            </span>
            <div class="post-description">从零开始的架构探险</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="《从零开始的架构探险》归纳总结"><a href="#《从零开始的架构探险》归纳总结" class="headerlink" title="《从零开始的架构探险》归纳总结"></a>《从零开始的架构探险》归纳总结</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>去年根据这本书实现了一个基本的SpringMVC框架，作者使用SpingMVC中依赖反转和AOP这两个核心概念用自己的理解写了一个框架。个人觉得对于SpringMVC的源码阅读是非常有帮助，现在再次回顾所学的内容</p>
<a id="more"></a>

<h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2><h3 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h3><p>框架的最终目的是为了解决现实中不断出现的某些问题，比如频繁的创建对象</p>
<ol>
<li>用户进入“客户管理”模块，列表展示所有用户</li>
<li>通过”用户名称”关键字查询</li>
<li>单击客户列表客户名称链接，可以查看客户基本信息</li>
<li>单击“新增”按钮，进入“新增客户界面”， 可以增加用户信息</li>
<li>单击“编辑”按钮，进入“编辑客户界面”， 可以编辑当前用户信息</li>
<li>单击“删除”按钮，可以删除当前用户，需要给出提示</li>
</ol>
<p>依照需求我们分析出基本用户信息为：</p>
<ol>
<li>名称</li>
<li>联系人</li>
<li>电话号码</li>
<li>邮箱</li>
<li>备注</li>
</ol>
<h3 id="设计接口"><a href="#设计接口" class="headerlink" title="设计接口"></a>设计接口</h3><ol>
<li><p>GET: /customer</p>
<p>进入客户列表页面</p>
</li>
<li><p>POST：/customer_search</p>
<p>查找对应用户</p>
</li>
<li><p>GET: /customer_show?id={id}</p>
<p>查看用户</p>
</li>
<li><p>GET:/customer_create</p>
<p>创建用户页面</p>
</li>
<li><p>POST:/customer_create</p>
<p>创建用户操作</p>
</li>
<li><p>GET:/customer_eidt?id={id}</p>
<p>修改用户页面</p>
</li>
<li><p>POST:/customer_eidt?id={id}</p>
<p>修改用户操作</p>
</li>
<li><p>GET:/customer_delete?id={id}</p>
<p>删除操作</p>
</li>
</ol>
<h2 id="准备开发环境："><a href="#准备开发环境：" class="headerlink" title="准备开发环境："></a>准备开发环境：</h2><h3 id="IntelinJ-IDEA"><a href="#IntelinJ-IDEA" class="headerlink" title="IntelinJ IDEA"></a>IntelinJ IDEA</h3><p>现在破解比较麻烦了，个人建议直接某宝或者某鱼上买个破解码，直接破解到2089年，没有必要浪费时间在工具的破解上面</p>
<h3 id="Maven"><a href="#Maven" class="headerlink" title="Maven"></a>Maven</h3><p>使用3.6以上的版本</p>
<h3 id="JDK"><a href="#JDK" class="headerlink" title="JDK"></a>JDK</h3><p>使用JDK1.8的版本</p>
<h3 id="Tomcat"><a href="#Tomcat" class="headerlink" title="Tomcat"></a>Tomcat</h3><p>使用Tomcat 8.5 的版本</p>
<h2 id="项目地址"><a href="#项目地址" class="headerlink" title="项目地址"></a>项目地址</h2><p>具体搭建流程不做演示，这里给出一个github地址作为参考</p>
<p><span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2xhenlUaW1lcy9zbWFydGZyYW13b3Jr" title="https://github.com/lazyTimes/smartframwork">https://github.com/lazyTimes/smartframwork<i class="fa fa-external-link"></i></span></p>
<p>这事框架地址，具体的实验放在一个chapter3的项目里面，git的地址如下：</p>
<h2 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h2><h3 id="工具类"><a href="#工具类" class="headerlink" title="工具类"></a>工具类</h3><p><img src="https://raw.githubusercontent.com/lazyTimes/imageRepository/master/img/Snipaste_2020-02-10_11-00-25.png?ynotemdtimestamp=1595748679079" alt="img"></p>
<h4 id=""><a href="#" class="headerlink" title=""></a></h4><h3 id="注解"><a href="#注解" class="headerlink" title="注解"></a>注解</h3><p><img src="http://null/" alt="image-20200211103431175"></p>
<h3 id="Bean"><a href="#Bean" class="headerlink" title="Bean"></a>Bean</h3><p><img src="http://null/" alt="image-20200211131451516"></p>
<h3 id="框架处理工具"><a href="#框架处理工具" class="headerlink" title="框架处理工具"></a>框架处理工具</h3><p><img src="http://null/" alt="image-20200211132349636"></p>
<h2 id="IOC实现思路"><a href="#IOC实现思路" class="headerlink" title="IOC实现思路"></a>IOC实现思路</h2><p>不是由用户去new 对象，而是在初始化的时候框架拿到所有的controller, 根据controller 中扫描到 的所有的inject 注解，根据此注解拿到所有的服务类信息</p>
<p>最简单的方式</p>
<ol>
<li>通过<code>beanHelper</code> 获取所有的<code>Bean Map</code></li>
<li>遍历映射关系，分别取出bean类与Bean 实例，进而通过反射获取类中所有的成员变量</li>
<li>遍历这些成员变量，查看是否带有@Inject 注解，如果存在，则从<code>BeanMap</code>当中取出<code>Bean</code>实例，</li>
<li>最后通过<code>RelectionUtil#setField</code> 修改当前成员变量的值</li>
</ol>
<h3 id="如何实现控制层的加载"><a href="#如何实现控制层的加载" class="headerlink" title="如何实现控制层的加载"></a>如何实现控制层的加载</h3><ol>
<li>获取所有定义了<code>Controller</code>的类</li>
<li>反射获取所有加了<code>Action()</code>的方法</li>
<li>封装一个请求对象和处理对象</li>
<li>请求对象和处理对象建立一个映射关系</li>
<li>将映射加入<code>Action Map</code></li>
</ol>
<h3 id="请求转发器"><a href="#请求转发器" class="headerlink" title="请求转发器"></a>请求转发器</h3><ol>
<li>通过<code>ControllerHelper</code> 获取<code>Handler</code> 对象</li>
<li>获取<code>Controller</code>类</li>
<li><code>BeanHelper</code>获取所有的<code>Contoller</code>实体对象</li>
<li><code>HttpServlet</code>获取所有的请求参数</li>
</ol>
<h3 id="核心代码："><a href="#核心代码：" class="headerlink" title="核心代码："></a>核心代码：</h3><p>IOC的核心是在框架启动的时候扫描对应的包下面的类注解，并且使用反射的方式对于类进行初始化操作</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;**</span><br><span class="line"> * 类加载工具类</span><br><span class="line"> *&#x2F;</span><br><span class="line">public final class MyClassUtil &#123;</span><br><span class="line"></span><br><span class="line">    private static final Logger LOGGER &#x3D; LoggerFactory.getLogger(MyClassUtil.class);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * @Description: 获取类加载器</span><br><span class="line">     * @Param: 无参数</span><br><span class="line">     * @return: 类加载器</span><br><span class="line">     * @Author: zhaoxudong</span><br><span class="line">     * @Date: 2019.9.8</span><br><span class="line">     *&#x2F;</span><br><span class="line">    public static ClassLoader getClassLoader() &#123;</span><br><span class="line">        return Thread.currentThread().getContextClassLoader();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * @param className     类名</span><br><span class="line">     * @param isInitialized 是否初始化</span><br><span class="line">     * @return 实体类</span><br><span class="line">     * @Description: 加载class类</span><br><span class="line">     * @Author zhaoxudong</span><br><span class="line">     * @Date 2019.9.8</span><br><span class="line">     *&#x2F;</span><br><span class="line">    public static Class&lt;?&gt; loadClass(String className, boolean isInitialized) &#123;</span><br><span class="line">        Class&lt;?&gt; cls;</span><br><span class="line">        try &#123;</span><br><span class="line">            cls &#x3D; Class.forName(className, isInitialized, getClassLoader());</span><br><span class="line">        &#125; catch (ClassNotFoundException e) &#123;</span><br><span class="line">            LOGGER.error(&quot;load class failure&quot;, e);</span><br><span class="line">            throw new RuntimeException(e);</span><br><span class="line">        &#125;</span><br><span class="line">        return cls;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * 获取指定包名下面的所有类</span><br><span class="line">     * 最为复杂也是最为核心的代码</span><br><span class="line">     *</span><br><span class="line">     * @param packageName 包名</span><br><span class="line">     *&#x2F;</span><br><span class="line">    public static Set&lt;Class&lt;?&gt;&gt; getClassesSet(String packageName) &#123;</span><br><span class="line">        &#x2F;&#x2F; 1. 创建set集合</span><br><span class="line">        Set&lt;Class&lt;?&gt;&gt; result &#x3D; new HashSet&lt;Class&lt;?&gt;&gt;();</span><br><span class="line">        &#x2F;&#x2F; 2. 获取枚举迭代器，使用递归的方式迭代所有的包</span><br><span class="line">        try &#123;</span><br><span class="line">            Enumeration&lt;URL&gt; enumeration &#x3D; getClassLoader().getResources(packageName.replace(&quot;.&quot;, &quot;&#x2F;&quot;));</span><br><span class="line">            while (enumeration.hasMoreElements()) &#123;</span><br><span class="line">                URL url &#x3D; enumeration.nextElement();</span><br><span class="line">                if (null !&#x3D; url) &#123;</span><br><span class="line">                    &#x2F;&#x2F; protocol 协议，获取协议</span><br><span class="line">                    String protocool &#x3D; url.getProtocol();</span><br><span class="line">                    &#x2F;&#x2F; 如果是一个文件</span><br><span class="line">                    if (protocool.equals(&quot;file&quot;)) &#123;</span><br><span class="line">                        &#x2F;&#x2F; 替换掉特殊符号</span><br><span class="line">                        String urlPath &#x3D; url.getPath().replaceAll(&quot;%20&quot;, &quot;&quot;);</span><br><span class="line">                        addClass(result, urlPath, packageName);</span><br><span class="line">                    &#125; else if (protocool.equals(&quot;jar&quot;)) &#123;</span><br><span class="line">                        &#x2F;&#x2F; 如果是jar包，获取jar包路径</span><br><span class="line">                        JarURLConnection jarURLConnection &#x3D; (JarURLConnection) url.openConnection();</span><br><span class="line">                        if (null !&#x3D; jarURLConnection) &#123;</span><br><span class="line">                            &#x2F;&#x2F; 获取jar包文件</span><br><span class="line">                            JarFile jarFile &#x3D; jarURLConnection.getJarFile();</span><br><span class="line">                            if (null !&#x3D; jarFile) &#123;</span><br><span class="line">                                Enumeration&lt;JarEntry&gt; entries &#x3D; jarFile.entries();</span><br><span class="line">                                &#x2F;&#x2F; 枚举迭代获取所有的jar包类</span><br><span class="line">                                while (entries.hasMoreElements()) &#123;</span><br><span class="line">                                    JarEntry jarEntry &#x3D; entries.nextElement();</span><br><span class="line">                                    &#x2F;&#x2F; 获取名称</span><br><span class="line">                                    String entryName &#x3D; jarEntry.getName();</span><br><span class="line">                                    if (entryName.equals(&quot;.class&quot;)) &#123;</span><br><span class="line">                                        String className &#x3D; entryName.substring(0, entryName.lastIndexOf(&quot;.&quot;))</span><br><span class="line">                                                .replaceAll(&quot;&#x2F;&quot;, &quot;.&quot;);</span><br><span class="line">                                        doAddClass(result, className);</span><br><span class="line">                                    &#125;</span><br><span class="line">                                &#125;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; catch (IOException e) &#123;</span><br><span class="line">            LOGGER.error(&quot;get class set failure&quot;, e);</span><br><span class="line">            throw new RuntimeException(e);</span><br><span class="line">        &#125;</span><br><span class="line">        return result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * 将对应类型的文件路径加入到对应的set内部</span><br><span class="line">     *</span><br><span class="line">     * @param classSet      所有的应用宝</span><br><span class="line">     * @param packagePath 文件路径</span><br><span class="line">     * @param packageName 包名</span><br><span class="line">     *&#x2F;</span><br><span class="line">    private static void addClass(Set&lt;Class&lt;?&gt;&gt; classSet, String packagePath, String packageName) &#123;</span><br><span class="line">        &#x2F;&#x2F;对于文件路径进行过滤操作</span><br><span class="line">        File[] files &#x3D; new File(packagePath).listFiles(new FileFilter() &#123;</span><br><span class="line">            public boolean accept(File file) &#123;</span><br><span class="line">                &#x2F;&#x2F; 如果是class 文件或者文件夹，允许</span><br><span class="line">                return (file.isFile() &amp;&amp; file.getName().endsWith(&quot;.class&quot;)) || file.isDirectory();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        for (File file : files) &#123;</span><br><span class="line">            &#x2F;&#x2F; 当前遍历目录的文件名</span><br><span class="line">            String fileName &#x3D; file.getName();</span><br><span class="line">            &#x2F;&#x2F; 如果是文件类型</span><br><span class="line">            if (file.isFile()) &#123;</span><br><span class="line">                String className &#x3D; fileName.substring(0, fileName.lastIndexOf(&quot;.&quot;));</span><br><span class="line">                if (MyStringUtil.isNotEmpty(className)) &#123;</span><br><span class="line">                    className &#x3D; packageName + &quot;.&quot; + className;</span><br><span class="line">                &#125;</span><br><span class="line">                doAddClass(classSet, className);</span><br><span class="line"></span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                &#x2F;&#x2F; 如果不是文件，则根据路径加载文件</span><br><span class="line">                String subPackagePath &#x3D; fileName;</span><br><span class="line">                if (MyStringUtil.isNotEmpty(packagePath)) &#123;</span><br><span class="line">                    subPackagePath &#x3D; packagePath + &quot;&#x2F;&quot; + subPackagePath;</span><br><span class="line">                &#125;</span><br><span class="line">                String subPackageName &#x3D; fileName;</span><br><span class="line">                if (MyStringUtil.isNotEmpty(packageName)) &#123;</span><br><span class="line">                    subPackageName &#x3D; packageName + &quot;.&quot; + subPackageName;</span><br><span class="line">                &#125;</span><br><span class="line">                &#x2F;&#x2F; 递归获取子包下面的文件</span><br><span class="line">                addClass(classSet, subPackagePath, subPackageName);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * 添加类名的统一方法</span><br><span class="line">     * 主要为根据包名加载类</span><br><span class="line">     *</span><br><span class="line">     * @param result    类集合</span><br><span class="line">     * @param className 类名</span><br><span class="line">     *&#x2F;</span><br><span class="line">    private static void doAddClass(Set&lt;Class&lt;?&gt;&gt; result, String className) &#123;</span><br><span class="line">        Class&lt;?&gt; cls &#x3D; loadClass(className, false);</span><br><span class="line">        result.add(cls);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="AOP-实现思路"><a href="#AOP-实现思路" class="headerlink" title="AOP 实现思路"></a>AOP 实现思路</h2><h3 id="定义切面注解"><a href="#定义切面注解" class="headerlink" title="定义切面注解"></a>定义切面注解</h3><p>value：表示注解类，用来指定controller这一类注解</p>
<h3 id="搭建代理框架"><a href="#搭建代理框架" class="headerlink" title="搭建代理框架"></a>搭建代理框架</h3><ol>
<li>使用链式调用的方法生产代理对象</li>
<li>需要写一个类，提供创建代理对象的方法，输入一个目标类和一组Proxy, 输出代理对象，用于创建所有的代理对象</li>
<li>使用切面来管理所有的代理对象创建，因为切面需要拿到目标方法以及被调用的前后增加逻辑，<ol>
<li>写一个抽象类，提供模板，具体实现中扩展，定为AspectProxy</li>
</ol>
</li>
<li>使用一个日志切面对于代理操作进行增强</li>
</ol>
<h3 id="加载AOP框架"><a href="#加载AOP框架" class="headerlink" title="加载AOP框架"></a>加载AOP框架</h3><p>整个框架使用ProxyManager 创建代理对象</p>
<p>将代理对象放入框架底层的Bean Map,通过IOC将被代理的对象注入到其他对象</p>
<ol>
<li>在BeanHelper 当中增加一个添加Bean实例的方法</li>
<li>扩展ClassHelper , 增加一个获取某个父类的所有子类或者实现类，以及获取带有某个注解的所有类的方法</li>
</ol>
<p>获取Aspect 注解中设置的注解类，若该注解不是Aspect 类，则可以调用ClassHelper#getClassSetByAnnotation 获取相关类， 放入目标类集合， 最终返回这些集合</p>
<p>需要将代理类以及目标类集合的映射关系获取，一个代理对应一个或者多个目标类，代理类指定是切面类，通过以下代码或者映射关系</p>
<p>代理类需要扩展AspectProxy抽象类,还需要Aspect注解，只有两者都满足，才能根据Aspect注解定义的注解属性去获取改注解对应的目标类集合，才能建立代理类与目标类的集合，才能返回映射</p>
<h3 id="核心代码"><a href="#核心代码" class="headerlink" title="核心代码"></a>核心代码</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line">public final class AopHelper &#123;</span><br><span class="line"></span><br><span class="line">    private static final Logger LOGGER &#x3D; LoggerFactory.getLogger(AopHelper.class);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    static &#123;</span><br><span class="line">        try &#123;</span><br><span class="line">            Map&lt;Class&lt;?&gt;, Set&lt;Class&lt;?&gt;&gt;&gt; proxyMap &#x3D; createProxyMap();</span><br><span class="line">            Map&lt;Class&lt;?&gt;, List&lt;Proxy&gt;&gt; targetMap &#x3D; createTargetMap(proxyMap);</span><br><span class="line">            for (Map.Entry&lt;Class&lt;?&gt;, List&lt;Proxy&gt;&gt; targetEntity : targetMap.entrySet()) &#123;</span><br><span class="line">                Class&lt;?&gt; targetClass &#x3D; targetEntity.getKey();</span><br><span class="line">                List&lt;Proxy&gt; proxyList &#x3D; targetEntity.getValue();</span><br><span class="line">                Object proxy &#x3D; ProxyManager.createProxy(targetClass, proxyList);</span><br><span class="line">                BeanHelper.setBeanMap(targetClass, proxy);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; catch (Exception e) &#123;</span><br><span class="line">            LOGGER.error(&quot;aop failure&quot;, e);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * 获取所有Aspect 目标集合</span><br><span class="line">     * @param aspect</span><br><span class="line">     * @return</span><br><span class="line">     * @throws Exception</span><br><span class="line">     *&#x2F;</span><br><span class="line">    private static Set&lt;Class&lt;?&gt;&gt; createTargetClassSet(Aspect aspect) throws Exception&#123;</span><br><span class="line">        Set&lt;Class&lt;?&gt;&gt; targetClassSet &#x3D; new HashSet&lt;Class&lt;?&gt;&gt;();</span><br><span class="line">        Class&lt;? extends Annotation&gt; annotation &#x3D; aspect.value();</span><br><span class="line">        if(annotation !&#x3D; null &amp;&amp; !annotation.equals(Aspect.class))&#123;</span><br><span class="line">            targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));</span><br><span class="line">        &#125;</span><br><span class="line">        return targetClassSet;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * 创建代理类和目标集合的映射</span><br><span class="line">     * @return</span><br><span class="line">     * @throws Exception</span><br><span class="line">     *&#x2F;</span><br><span class="line">    private static Map&lt;Class&lt;?&gt;, Set&lt;Class&lt;?&gt;&gt;&gt; createProxyMap() throws Exception &#123;</span><br><span class="line">        Map&lt;Class&lt;?&gt;, Set&lt;Class&lt;?&gt;&gt;&gt; proxyMap &#x3D; new HashMap&lt;Class&lt;?&gt;, Set&lt;Class&lt;?&gt;&gt;&gt;();</span><br><span class="line">        Set&lt;Class&lt;?&gt;&gt; proxySet &#x3D; ClassHelper.getClassSetBySuper(AspectProxy.class);</span><br><span class="line">        for (Class&lt;?&gt; proxyClass: proxySet) &#123;</span><br><span class="line">            if(proxyClass.isAnnotationPresent(Aspect.class))&#123;</span><br><span class="line">                Aspect aspect &#x3D; proxyClass.getAnnotation(Aspect.class);</span><br><span class="line">                Set&lt;Class&lt;?&gt;&gt; targetClassSet &#x3D; createTargetClassSet(aspect);</span><br><span class="line">                proxyMap.put(proxyClass, targetClassSet);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return proxyMap;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#x2F;**</span><br><span class="line">     * 根据代理类和目标集合，分析出目标类和代理对象之间的映射</span><br><span class="line">     * @return</span><br><span class="line">     *&#x2F;</span><br><span class="line">    private static Map&lt;Class&lt;?&gt;, List&lt;Proxy&gt;&gt; createTargetMap(Map&lt;Class&lt;?&gt;,Set&lt;Class&lt;?&gt;&gt;&gt; proxyMap) throws Exception &#123;</span><br><span class="line">        Map&lt;Class&lt;?&gt;,List&lt;Proxy&gt;&gt; targetMap &#x3D; new HashMap&lt;Class&lt;?&gt;, List&lt;Proxy&gt;&gt;();</span><br><span class="line">        for (Map.Entry&lt;Class&lt;?&gt;, Set&lt;Class&lt;?&gt;&gt;&gt; proxyEntity : proxyMap.entrySet()) &#123;</span><br><span class="line">            Class&lt;?&gt; proxyClass &#x3D; proxyEntity.getKey();</span><br><span class="line">            Set&lt;Class&lt;?&gt;&gt; targetClassSet &#x3D; proxyEntity.getValue();</span><br><span class="line">            for (Class&lt;?&gt; targetClass: targetClassSet) &#123;</span><br><span class="line">                Proxy proxy &#x3D; (Proxy)proxyClass.newInstance();</span><br><span class="line">                if(targetMap.containsKey(targetClass))&#123;</span><br><span class="line">                    targetMap.get(targetClass).add(proxy);</span><br><span class="line">                &#125;else&#123;</span><br><span class="line">                    List&lt;Proxy&gt; proxyList &#x3D; new ArrayList&lt;Proxy&gt;();</span><br><span class="line">                    proxyList.add(proxy);</span><br><span class="line">                    targetMap.put(targetClass, proxyList);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return targetMap;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="问题汇总："><a href="#问题汇总：" class="headerlink" title="问题汇总："></a>问题汇总：</h1><h2 id="Spring是如何处理请求路径中的-quot-quot-的？"><a href="#Spring是如何处理请求路径中的-quot-quot-的？" class="headerlink" title="Spring是如何处理请求路径中的&quot;/&quot;的？"></a>Spring是如何处理请求路径中的<code>&quot;/&quot;</code>的？</h2><p>例如：<code>&quot;/hello&quot;</code>和<code>&quot;hello&quot;</code>效果是一样的</p>
<p>目前做了一个<code>startWith()</code>的判断操作</p>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/kity@2.0.4/dist/kity.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text/javascript" src="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.2.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.2.0/dist/mindmap.min.css">
    </div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>lazytime
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://whitestore.top/2020/07/26/note4/" title="《从零开始的架构探险》归纳总结">https://whitestore.top/2020/07/26/note4/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <span class="exturl" data-url="aHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzQuMC96aC1DTg=="><i class="fa fa-fw fa-creative-commons"></i>BY-NC</span> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/" rel="tag"># 读书笔记</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2020/07/26/corscaikeng/" rel="prev" title="记一次CORS踩坑记录">
      <i class="fa fa-chevron-left"></i> 记一次CORS踩坑记录
    </a></div>
      <div class="post-nav-item">
    <a href="/2020/07/26/note5/" rel="next" title="使用Hibernate JSP 303 整合到SSM项目">
      使用Hibernate JSP 303 整合到SSM项目 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          
    <div class="comments" id="valine-comments"></div>

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#《从零开始的架构探险》归纳总结"><span class="nav-number">1.</span> <span class="nav-text">《从零开始的架构探险》归纳总结</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#前言"><span class="nav-number">1.1.</span> <span class="nav-text">前言</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#起步"><span class="nav-number">1.2.</span> <span class="nav-text">起步</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#需求分析"><span class="nav-number">1.2.1.</span> <span class="nav-text">需求分析</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#设计接口"><span class="nav-number">1.2.2.</span> <span class="nav-text">设计接口</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#准备开发环境："><span class="nav-number">1.3.</span> <span class="nav-text">准备开发环境：</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#IntelinJ-IDEA"><span class="nav-number">1.3.1.</span> <span class="nav-text">IntelinJ IDEA</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Maven"><span class="nav-number">1.3.2.</span> <span class="nav-text">Maven</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JDK"><span class="nav-number">1.3.3.</span> <span class="nav-text">JDK</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Tomcat"><span class="nav-number">1.3.4.</span> <span class="nav-text">Tomcat</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#项目地址"><span class="nav-number">1.4.</span> <span class="nav-text">项目地址</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#项目结构"><span class="nav-number">1.5.</span> <span class="nav-text">项目结构</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#工具类"><span class="nav-number">1.5.1.</span> <span class="nav-text">工具类</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#"><span class="nav-number">1.5.1.1.</span> <span class="nav-text"></span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#注解"><span class="nav-number">1.5.2.</span> <span class="nav-text">注解</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Bean"><span class="nav-number">1.5.3.</span> <span class="nav-text">Bean</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#框架处理工具"><span class="nav-number">1.5.4.</span> <span class="nav-text">框架处理工具</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#IOC实现思路"><span class="nav-number">1.6.</span> <span class="nav-text">IOC实现思路</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#如何实现控制层的加载"><span class="nav-number">1.6.1.</span> <span class="nav-text">如何实现控制层的加载</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#请求转发器"><span class="nav-number">1.6.2.</span> <span class="nav-text">请求转发器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#核心代码："><span class="nav-number">1.6.3.</span> <span class="nav-text">核心代码：</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOP-实现思路"><span class="nav-number">1.7.</span> <span class="nav-text">AOP 实现思路</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#定义切面注解"><span class="nav-number">1.7.1.</span> <span class="nav-text">定义切面注解</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#搭建代理框架"><span class="nav-number">1.7.2.</span> <span class="nav-text">搭建代理框架</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#加载AOP框架"><span class="nav-number">1.7.3.</span> <span class="nav-text">加载AOP框架</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#核心代码"><span class="nav-number">1.7.4.</span> <span class="nav-text">核心代码</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#问题汇总："><span class="nav-number">2.</span> <span class="nav-text">问题汇总：</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring是如何处理请求路径中的-quot-quot-的？"><span class="nav-number">2.1.</span> <span class="nav-text">Spring是如何处理请求路径中的&quot;&#x2F;&quot;的？</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">阿东</p>
  <div class="site-description" itemprop="description">随遇而安</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">239</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">36</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">37</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2xhenlUaW1lcw==" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;lazyTimes"><i class="fa fa-fw fa-github"></i>GitHub</span>
      </span>
      <span class="links-of-author-item">
        <span class="exturl" data-url="bWFpbHRvOjEwOTc0ODM1MDhAcXEuY29t" title="E-Mail → mailto:1097483508@qq.com"><i class="fa fa-fw fa-envelope"></i>E-Mail</span>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title">
      <i class="fa fa-fw fa-link"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cHM6Ly93d3cuNTJwb2ppZS5jbi9ob21lLnBocD9tb2Q9c3BhY2UmdWlkPTE0OTc3MTgmZG89dGhyZWFkJnZpZXc9bWUmZnJvbT1zcGFjZQ==" title="https:&#x2F;&#x2F;www.52pojie.cn&#x2F;home.php?mod&#x3D;space&amp;uid&#x3D;1497718&amp;do&#x3D;thread&amp;view&#x3D;me&amp;from&#x3D;space">吾爱破解</span>
        </li>
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cHM6Ly9qdWVqaW4uaW0vdXNlci8yOTk5MTIzNDUyNjI2MzY2" title="https:&#x2F;&#x2F;juejin.im&#x2F;user&#x2F;2999123452626366">掘金</span>
        </li>
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cHM6Ly9zZWdtZW50ZmF1bHQuY29tL3UvbGF6eXRpbWVz" title="https:&#x2F;&#x2F;segmentfault.com&#x2F;u&#x2F;lazytimes">思否</span>
        </li>
    </ul>
  </div>

      </div>

      <div class="wechat_OA">
        <span>欢迎关注我的公众号</span>
        <br>
          <!-- 这里添加你的二维码图片 -->
        <img src ="https://adong-picture.oss-cn-shenzhen.aliyuncs.com/adong/wechat_channel.jpg">
      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">阿东</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    <span title="站点总字数">2m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">29:50</span>
</div>
  <div class="powered-by">由 <span class="exturl theme-link" data-url="aHR0cHM6Ly9oZXhvLmlv">Hexo</span> & <span class="exturl theme-link" data-url="aHR0cHM6Ly90aGVtZS1uZXh0Lm9yZw==">NexT.Gemini</span> 强力驱动
  </div>

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/fancyapps/fancybox@3/dist/jquery.fancybox.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : true,
      appId      : 'qMUpEEvBgXaMDD1b0ftgi9xr-gzGzoHsz',
      appKey     : 'UCdfT4Rfih6MO6y8DI4fstf6',
      placeholder: "Just go go",
      avatar     : 'mm',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : false,
      lang       : 'zh-CN' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

</body>
</html>
